package 状态机.请假demo.handler;

import 状态机.请假demo.entity.LeavePermit;
import 状态机.请假demo.machine.IStatusMachine;
import 状态机.请假demo.machine.StatusMachineEngine;
import 状态机.请假demo.machine.StatusMachineFactory;
import 状态机.请假demo.status.Status;

public abstract class CommonStatusHandler implements IStatusHandler {
    @Override
    public void handler(LeavePermit leavePermit) {
        before(leavePermit);
        doSpecificHandler(leavePermit);
        after(leavePermit);
    }

    /**
     * 处理假条之前做点啥，例如记录日志
     *
     * @param leavePermit
     */
    private void before(LeavePermit leavePermit) {

    }

    /**
     * 选择具体的处理者来审批假单，他们将给出具体的审批意见，该意见就是一个 Event
     *
     * @param leavePermit
     */
    protected abstract void doSpecificHandler(LeavePermit leavePermit);

    /**
     * Event 发生之后需要进入新状态。
     * 也就是：当前状态 + 当前发生的事件 ---> 转移到下一个状态
     * <p>
     * after 就是负责完成这一动作的方法
     *
     * @param leavePermit
     */
    public void after(LeavePermit leavePermit) {
        goNextStatusHandler(leavePermit);
    }

    public void goNextStatusHandler(LeavePermit leavePermit) {
        /*
         * 获取下一个状态
         *
         * 首先通过 当前的假单类型 从 StatusMachineFactory 中获取 具体处理者状态机 ，**该状态机存储着当前状态跳往的下一个状态**
         * 若当前状态跳往的下一个状态有多个，还需要结合当前的 Event 来辅助判断
         *
         * 然后更新此假单的状态
         */
        IStatusMachine machine = StatusMachineFactory.getStatusMachine(leavePermit.getLeavePermitType());
        Status status = machine.getNextStatus(leavePermit.getStatus(), leavePermit.getEvent());
        leavePermit.setStatus(status);

        StatusMachineEngine.post(leavePermit);
    }
}
